package com.xxl.config;

import com.xxl.pojo.User;
import com.xxl.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;

import javax.annotation.Resource;

/**
 * shiro的安全认证核心
 * @author xxl
 * @date 2023/3/12
 */
public class UserRealm extends AuthorizingRealm {
    @Resource
    UserService service;
    /**
     * 权限认证(授权)
     * @author xxl
     * @param  principals
     * @return AuthorizationInfo
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("授权,principals="+principals.toString());
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //拿到当前用户
        Subject subject = SecurityUtils.getSubject();
        //这个取的值就是身份认证存的Principal也可以通过此方法的参数
        User principal = (User)subject.getPrincipal();
        //设置当前用户权限
        info.addStringPermission(principal.getStatus());
        //设置用户角色
        info.addRole("admin");
        System.out.println("subject=" + subject);
        return info;
    }

    /**
     * 身份认证(账户验证)，一旦用了perms/role过滤器就会此方法
     * @param token
     * @return AuthenticationInfo
     * @author xxl
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("身份认证");


        //获取控制器封装的额token
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;

        /*
          开始验证账户：这里返回null控制器就会抛出 UnknownAccountException异常
          密码验证由shiro做
        */
        User user = service.findUserByName(userToken.getUsername());
        if (user == null) {
            return null;
        }
        /*
          principal：认证(用户)：这里存放用户，权限认证就会拿到
          credentials：凭证(密码)：这个密码数据库查出来的，它会跟前端的密码最比较
          realmName：角色名
        */
        return new SimpleAuthenticationInfo(user, user.getPwd(), "");
    }

}
